From: mjw@wray-m-3.hpl.hp.com Date: Thu, 23 Sep 2004 13:42:03 +0000 (+0000) Subject: bitkeeper revision 1.1159.82.1 (4152d2abNRTmjgcJM5fkbYQyAoi9pA) X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~17400^2~583^2~1 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https://%22%22/%22http:/www.example.com/cgi/%22https:/%22%22?a=commitdiff_plain;h=946648e0db7cbf8be5b962eff92de1029ac98b47;p=xen.git bitkeeper revision 1.1159.82.1 (4152d2abNRTmjgcJM5fkbYQyAoi9pA) Change device messaging to support adding netifs at runtime, and to support front-end polling. --- diff --git a/linux-2.6.8.1-xen-sparse/drivers/xen/blkback/control.c b/linux-2.6.8.1-xen-sparse/drivers/xen/blkback/control.c index 0b26224651..b55bae7b1f 100644 --- a/linux-2.6.8.1-xen-sparse/drivers/xen/blkback/control.c +++ b/linux-2.6.8.1-xen-sparse/drivers/xen/blkback/control.c @@ -71,16 +71,16 @@ static void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) void blkif_ctrlif_init(void) { - ctrl_msg_t cmsg; - blkif_be_driver_status_changed_t st; + ctrl_msg_t cmsg; + blkif_be_driver_status_t st; (void)ctrl_if_register_receiver(CMSG_BLKIF_BE, blkif_ctrlif_rx, CALLBACK_IN_BLOCKING_CONTEXT); /* Send a driver-UP notification to the domain controller. */ cmsg.type = CMSG_BLKIF_BE; - cmsg.subtype = CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED; - cmsg.length = sizeof(blkif_be_driver_status_changed_t); + cmsg.subtype = CMSG_BLKIF_BE_DRIVER_STATUS; + cmsg.length = sizeof(blkif_be_driver_status_t); st.status = BLKIF_DRIVER_STATUS_UP; memcpy(cmsg.msg, &st, sizeof(st)); ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); diff --git a/linux-2.6.8.1-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6.8.1-xen-sparse/drivers/xen/blkfront/blkfront.c index 259275ebd1..e282c1e245 100644 --- a/linux-2.6.8.1-xen-sparse/drivers/xen/blkfront/blkfront.c +++ b/linux-2.6.8.1-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -1010,23 +1010,23 @@ void blkif_control_send(blkif_request_t *req, blkif_response_t *rsp) } -static void blkif_status_change(blkif_fe_interface_status_changed_t *status) +static void blkif_status_change(blkif_fe_interface_status_t *status) { ctrl_msg_t cmsg; blkif_fe_interface_connect_t up; long rc; - if ( status->handle != 0 ) - { - printk(KERN_WARNING "Status change on unsupported blkif %d\n", - status->handle); - return; - } +/* if ( status->handle != 0 ) */ +/* { */ +/* printk(KERN_WARNING "Status change on unsupported blkif %d\n", */ +/* status->handle); */ +/* return; */ +/* } */ switch ( status->status ) { - case BLKIF_INTERFACE_STATUS_DESTROYED: - printk(KERN_WARNING "Unexpected blkif-DESTROYED message in state %d\n", + case BLKIF_INTERFACE_STATUS_CLOSED: + printk(KERN_WARNING "Unexpected blkif-CLOSED message in state %d\n", blkif_state); break; @@ -1148,11 +1148,11 @@ static void blkif_status_change(blkif_fe_interface_status_changed_t *status) break; - case BLKIF_INTERFACE_STATUS_CHANGED: - /* The domain controller is notifying us that a device has been - * added or removed. - */ - break; +// case BLKIF_INTERFACE_STATUS_CHANGED: +// /* The domain controller is notifying us that a device has been +// * added or removed. +// */ +// break; default: printk(KERN_WARNING "Status change to unknown value %d\n", @@ -1166,14 +1166,14 @@ static void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) { switch ( msg->subtype ) { - case CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED: - if ( msg->length != sizeof(blkif_fe_interface_status_changed_t) ) + case CMSG_BLKIF_FE_INTERFACE_STATUS: + if ( msg->length != sizeof(blkif_fe_interface_status_t) ) goto parse_error; - blkif_status_change((blkif_fe_interface_status_changed_t *) + blkif_status_change((blkif_fe_interface_status_t *) &msg->msg[0]); break; #if 0 - case CMSG_BLKIF_FE_VBD_STATUS_CHANGED: + case CMSG_BLKIF_FE_VBD_STATUS: update_tq.routine = update_vbds_task; schedule_task(&update_tq); break; @@ -1194,7 +1194,7 @@ static void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) int __init xlblk_init(void) { ctrl_msg_t cmsg; - blkif_fe_driver_status_changed_t st; + blkif_fe_driver_status_t st; int i; if ( (start_info.flags & SIF_INITDOMAIN) @@ -1215,8 +1215,8 @@ int __init xlblk_init(void) /* Send a driver-UP notification to the domain controller. */ cmsg.type = CMSG_BLKIF_FE; - cmsg.subtype = CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED; - cmsg.length = sizeof(blkif_fe_driver_status_changed_t); + cmsg.subtype = CMSG_BLKIF_FE_DRIVER_STATUS; + cmsg.length = sizeof(blkif_fe_driver_status_t); st.status = BLKIF_DRIVER_STATUS_UP; memcpy(cmsg.msg, &st, sizeof(st)); ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); @@ -1245,12 +1245,12 @@ void blkdev_suspend(void) void blkdev_resume(void) { ctrl_msg_t cmsg; - blkif_fe_driver_status_changed_t st; + blkif_fe_driver_status_t st; /* Send a driver-UP notification to the domain controller. */ cmsg.type = CMSG_BLKIF_FE; - cmsg.subtype = CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED; - cmsg.length = sizeof(blkif_fe_driver_status_changed_t); + cmsg.subtype = CMSG_BLKIF_FE_DRIVER_STATUS; + cmsg.length = sizeof(blkif_fe_driver_status_t); st.status = BLKIF_DRIVER_STATUS_UP; memcpy(cmsg.msg, &st, sizeof(st)); ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); diff --git a/linux-2.6.8.1-xen-sparse/drivers/xen/netback/control.c b/linux-2.6.8.1-xen-sparse/drivers/xen/netback/control.c index cf1b075031..6ca0ba2c75 100644 --- a/linux-2.6.8.1-xen-sparse/drivers/xen/netback/control.c +++ b/linux-2.6.8.1-xen-sparse/drivers/xen/netback/control.c @@ -49,16 +49,16 @@ static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) void netif_ctrlif_init(void) { - ctrl_msg_t cmsg; - netif_be_driver_status_changed_t st; + ctrl_msg_t cmsg; + netif_be_driver_status_t st; (void)ctrl_if_register_receiver(CMSG_NETIF_BE, netif_ctrlif_rx, CALLBACK_IN_BLOCKING_CONTEXT); /* Send a driver-UP notification to the domain controller. */ cmsg.type = CMSG_NETIF_BE; - cmsg.subtype = CMSG_NETIF_BE_DRIVER_STATUS_CHANGED; - cmsg.length = sizeof(netif_be_driver_status_changed_t); + cmsg.subtype = CMSG_NETIF_BE_DRIVER_STATUS; + cmsg.length = sizeof(netif_be_driver_status_t); st.status = NETIF_DRIVER_STATUS_UP; memcpy(cmsg.msg, &st, sizeof(st)); ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); diff --git a/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c index f04c6a1b59..485d23b8d1 100644 --- a/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c @@ -29,13 +29,30 @@ #include #include -#if 0 +#define DEBUG 0 + +#if DEBUG + #define DPRINTK(fmt, args...) \ printk(KERN_INFO "[XEN] %s" fmt, __FUNCTION__, ##args) + #else + #define DPRINTK(fmt, args...) ((void)0) + #endif +#define IPRINTK(fmt, args...) \ + printk(KERN_INFO "[XEN]" fmt, ##args) + +#define WPRINTK(fmt, args...) \ + printk(KERN_WARNING "[XEN]" fmt, ##args) + +#define EPRINTK(fmt, args...) \ + printk(KERN_ERROR "[XEN]" fmt, ##args) + + + #ifndef __GFP_NOWARN #define __GFP_NOWARN 0 #endif @@ -101,6 +118,24 @@ struct net_private struct sk_buff *rx_skbs[NETIF_RX_RING_SIZE+1]; }; +static char * status_name[] = { + [NETIF_INTERFACE_STATUS_CLOSED] = "closed", + [NETIF_INTERFACE_STATUS_DISCONNECTED] = "disconnected", + [NETIF_INTERFACE_STATUS_CONNECTED] = "connected", + [NETIF_INTERFACE_STATUS_CHANGED] = "changed", +}; + +static char * be_state_name[] = { + [BEST_CLOSED] = "closed", + [BEST_DISCONNECTED] = "disconnected", + [BEST_CONNECTED] = "connected", +}; + +static char * user_state_name[] = { + [UST_CLOSED] = "closed", + [UST_OPEN] = "open", +}; + /* Access macros for acquiring freeing slots in {tx,rx}_skbs[]. */ #define ADD_ID_TO_FREELIST(_list, _id) \ (_list)[(_id)] = (_list)[0]; \ @@ -131,6 +166,7 @@ struct netif_ctrl { int connected_n; /** Error code. */ int err; + int up; }; static struct netif_ctrl netctrl; @@ -138,15 +174,16 @@ static struct netif_ctrl netctrl; static void netctrl_init(void) { memset(&netctrl, 0, sizeof(netctrl)); - netctrl.interface_n = -1; + netctrl.up = NETIF_DRIVER_STATUS_DOWN; } /** Get or set a network interface error. */ static int netctrl_err(int err) { - if ( (err < 0) && !netctrl.err ) + if ( (err < 0) && !netctrl.err ){ netctrl.err = err; + } return netctrl.err; } @@ -157,8 +194,12 @@ static int netctrl_err(int err) static int netctrl_connected(void) { int ok = 0; - ok = (netctrl.err ? netctrl.err : - (netctrl.connected_n == netctrl.interface_n)); + + if(netctrl.err){ + ok = netctrl.err; + } else if(netctrl.up == NETIF_DRIVER_STATUS_UP){ + ok = (netctrl.connected_n == netctrl.interface_n); + } return ok; } @@ -175,11 +216,11 @@ static int netctrl_connected_count(void) connected = 0; - list_for_each(ent, &dev_list) - { + list_for_each(ent, &dev_list) { np = list_entry(ent, struct net_private, list); - if ( np->backend_state == BEST_CONNECTED ) + if (np->backend_state == BEST_CONNECTED){ connected++; + } } netctrl.connected_n = connected; @@ -589,7 +630,7 @@ static struct net_device_stats *network_get_stats(struct net_device *dev) static void network_connect(struct net_device *dev, - netif_fe_interface_status_changed_t *status) + netif_fe_interface_status_t *status) { struct net_private *np; int i, requeue_idx; @@ -647,8 +688,8 @@ static void network_connect(struct net_device *dev, wmb(); np->rx->req_prod = requeue_idx; -printk(KERN_ALERT"Netfront recovered tx=%d rxfree=%d\n", - np->tx->req_prod,np->rx->req_prod); + printk(KERN_ALERT "[XEN] Netfront recovered tx=%d rxfree=%d\n", + np->tx->req_prod,np->rx->req_prod); /* Step 3: All public and private state should now be sane. Get @@ -668,130 +709,155 @@ printk(KERN_ALERT"Netfront recovered tx=%d rxfree=%d\n", spin_unlock_irq(&np->rx_lock); } -static void netif_status_change(netif_fe_interface_status_changed_t *status) -{ - ctrl_msg_t cmsg; - netif_fe_interface_connect_t up; - struct net_device *dev; - struct net_private *np; - - DPRINTK(">\n"); - DPRINTK("> status=%d handle=%d mac=%02x:%02x:%02x:%02x:%02x:%02x\n", - status->status, - status->handle, - status->mac[0], status->mac[1], status->mac[2], - status->mac[3], status->mac[4], status->mac[5]); - - if ( netctrl.interface_n <= 0 ) - { - printk(KERN_WARNING "Status change: no interfaces\n"); - return; +static void vif_show(struct net_private *np){ +#if DEBUG + if(np){ + IPRINTK(" \n", + np->handle, + be_state_name[np->backend_state], + user_state_name[np->user_state], + np->evtchn, + np->irq, + np->tx, + np->rx); + } else { + IPRINTK("\n"); } +#endif +} - dev = find_dev_by_handle(status->handle); - if(!dev){ - printk(KERN_WARNING "Status change: invalid netif handle %u\n", - status->handle); - return; - } - np = dev->priv; - - switch ( status->status ) - { - case NETIF_INTERFACE_STATUS_DESTROYED: - printk(KERN_WARNING "Unexpected netif-DESTROYED message in state %d\n", - np->backend_state); - break; +/* Send a connect message to xend to tell it to bring up the interface. + */ +static void send_interface_connect(struct net_private *np){ + ctrl_msg_t cmsg = { + .type = CMSG_NETIF_FE, + .subtype = CMSG_NETIF_FE_INTERFACE_CONNECT, + .length = sizeof(netif_fe_interface_connect_t), + }; + netif_fe_interface_connect_t *msg = (void*)cmsg.msg; + + DPRINTK(">\n"); vif_show(np); + msg->handle = np->handle; + msg->tx_shmem_frame = (virt_to_machine(np->tx) >> PAGE_SHIFT); + msg->rx_shmem_frame = (virt_to_machine(np->rx) >> PAGE_SHIFT); + + ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); + DPRINTK("<\n"); +} - case NETIF_INTERFACE_STATUS_DISCONNECTED: - if ( np->backend_state != BEST_CLOSED ) - { - printk(KERN_WARNING "Unexpected netif-DISCONNECTED message" - " in state %d\n", np->backend_state); - printk(KERN_INFO "Attempting to reconnect network interface\n"); - - /* Begin interface recovery. - * - * NB. Whilst we're recovering, we turn the carrier state off. We - * take measures to ensure that this device isn't used for - * anything. We also stop the queue for this device. Various - * different approaches (e.g. continuing to buffer packets) have - * been tested but don't appear to improve the overall impact on - * TCP connections. - * - * TODO: (MAW) Change the Xend<->Guest protocol so that a recovery - * is initiated by a special "RESET" message - disconnect could - * just mean we're not allowed to use this interface any more. - */ - - /* Stop old i/f to prevent errors whilst we rebuild the state. */ - spin_lock_irq(&np->tx_lock); - spin_lock(&np->rx_lock); - netif_stop_queue(dev); - np->backend_state = BEST_DISCONNECTED; - spin_unlock(&np->rx_lock); - spin_unlock_irq(&np->tx_lock); - - /* Free resources. */ - free_irq(np->irq, dev); - unbind_evtchn_from_irq(np->evtchn); - free_page((unsigned long)np->tx); - free_page((unsigned long)np->rx); - } +/* Send a driver status notification to the domain controller. */ +static int send_driver_status(int ok) +{ + int err = 0; + ctrl_msg_t cmsg = { + .type = CMSG_NETIF_FE, + .subtype = CMSG_NETIF_FE_DRIVER_STATUS, + .length = sizeof(netif_fe_driver_status_t), + }; + netif_fe_driver_status_t *msg = (void*)cmsg.msg; + + msg->status = (ok ? NETIF_DRIVER_STATUS_UP : NETIF_DRIVER_STATUS_DOWN); + err = ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); + return err; +} - /* Move from CLOSED to DISCONNECTED state. */ - np->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL); - np->rx = (netif_rx_interface_t *)__get_free_page(GFP_KERNEL); - memset(np->tx, 0, PAGE_SIZE); - memset(np->rx, 0, PAGE_SIZE); - np->backend_state = BEST_DISCONNECTED; - - /* Construct an interface-CONNECT message for the domain controller. */ - cmsg.type = CMSG_NETIF_FE; - cmsg.subtype = CMSG_NETIF_FE_INTERFACE_CONNECT; - cmsg.length = sizeof(netif_fe_interface_connect_t); - up.handle = status->handle; - up.tx_shmem_frame = virt_to_machine(np->tx) >> PAGE_SHIFT; - up.rx_shmem_frame = virt_to_machine(np->rx) >> PAGE_SHIFT; - memcpy(cmsg.msg, &up, sizeof(up)); - - /* Tell the controller to bring up the interface. */ - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); - break; +/* Stop network device and free tx/rx queues and irq. + */ +static void vif_release(struct net_private *np){ - case NETIF_INTERFACE_STATUS_CONNECTED: - if ( np->backend_state == BEST_CLOSED ) - { - printk(KERN_WARNING "Unexpected netif-CONNECTED message" - " in state %d\n", np->backend_state); - break; - } + /* Stop old i/f to prevent errors whilst we rebuild the state. */ + spin_lock_irq(&np->tx_lock); + spin_lock(&np->rx_lock); + netif_stop_queue(np->dev); + //np->backend_state = BEST_DISCONNECTED; + spin_unlock(&np->rx_lock); + spin_unlock_irq(&np->tx_lock); + + /* Free resources. */ + if(np->tx != NULL){ + free_irq(np->irq, np->dev); + unbind_evtchn_from_irq(np->evtchn); + free_page((unsigned long)np->tx); + free_page((unsigned long)np->rx); + np->irq = 0; + np->evtchn = 0; + np->tx = NULL; + np->rx = NULL; + } - memcpy(dev->dev_addr, status->mac, ETH_ALEN); +} - network_connect(dev, status); +/* Release vif resources and close it down completely. + */ +static void vif_close(struct net_private *np){ + DPRINTK(">\n"); vif_show(np); + WPRINTK(" Unexpected netif-CLOSED message in state %s\n", + be_state_name[np->backend_state]); + vif_release(np); + np->backend_state = BEST_CLOSED; + //todo: take dev down and free. + vif_show(np); DPRINTK("<\n"); +} - np->evtchn = status->evtchn; - np->irq = bind_evtchn_to_irq(np->evtchn); - (void)request_irq(np->irq, netif_int, SA_SAMPLE_RANDOM, - dev->name, dev); - netctrl_connected_count(); - vif_wake(dev); - break; +/* Move the vif into disconnected state. + * Allocates tx/rx pages. + * Sends connect message to xend. + */ +static void vif_disconnect(struct net_private *np){ + DPRINTK(">\n"); + if(np->tx) free_page((unsigned long)np->tx); + if(np->rx) free_page((unsigned long)np->rx); + // Before this np->tx and np->rx had better be null. + np->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL); + np->rx = (netif_rx_interface_t *)__get_free_page(GFP_KERNEL); + memset(np->tx, 0, PAGE_SIZE); + memset(np->rx, 0, PAGE_SIZE); + np->backend_state = BEST_DISCONNECTED; + send_interface_connect(np); + vif_show(np); DPRINTK("<\n"); +} - case NETIF_INTERFACE_STATUS_CHANGED: - /* The domain controller is notifying us that a device has been - * added or removed. - */ - break; +/* Begin interface recovery. + * + * NB. Whilst we're recovering, we turn the carrier state off. We + * take measures to ensure that this device isn't used for + * anything. We also stop the queue for this device. Various + * different approaches (e.g. continuing to buffer packets) have + * been tested but don't appear to improve the overall impact on + * TCP connections. + * + * TODO: (MAW) Change the Xend<->Guest protocol so that a recovery + * is initiated by a special "RESET" message - disconnect could + * just mean we're not allowed to use this interface any more. + */ +static void vif_reset(struct net_private *np){ + DPRINTK(">\n"); + IPRINTK(" Attempting to reconnect network interface: handle=%u\n", + np->handle); + + vif_release(np); + vif_disconnect(np); + vif_show(np); DPRINTK("<\n"); +} - default: - printk(KERN_WARNING "Status change to unknown value %d\n", - status->status); - break; - } +/* Move the vif into connected state. + * Sets the mac and event channel from the message. + * Binds the irq to the event channel. + */ +static void vif_connect(struct net_private *np, netif_fe_interface_status_t *status){ + struct net_device *dev = np->dev; + DPRINTK(">\n"); + memcpy(dev->dev_addr, status->mac, ETH_ALEN); + network_connect(dev, status); + np->evtchn = status->evtchn; + np->irq = bind_evtchn_to_irq(np->evtchn); + (void)request_irq(np->irq, netif_int, SA_SAMPLE_RANDOM, dev->name, dev); + netctrl_connected_count(); + vif_wake(dev); + vif_show(np); DPRINTK("<\n"); } + /** Create a network device. * @param handle device handle * @param val return parameter for created device @@ -819,10 +885,12 @@ static int create_netdev(int handle, struct net_device **val) spin_lock_init(&np->rx_lock); /* Initialise {tx,rx}_skbs to be a free chain containing every entry. */ - for ( i = 0; i <= NETIF_TX_RING_SIZE; i++ ) + for ( i = 0; i <= NETIF_TX_RING_SIZE; i++ ){ np->tx_skbs[i] = (void *)(i+1); - for ( i = 0; i <= NETIF_RX_RING_SIZE; i++ ) + } + for ( i = 0; i <= NETIF_RX_RING_SIZE; i++ ){ np->rx_skbs[i] = (void *)(i+1); + } dev->open = network_open; dev->hard_start_xmit = network_start_xmit; @@ -840,58 +908,172 @@ static int create_netdev(int handle, struct net_device **val) list_add(&np->list, &dev_list); exit: - if ( (err != 0) && (dev != NULL ) ) + if ( (err != 0) && (dev != NULL ) ){ kfree(dev); - else if ( val != NULL ) + } else if ( val != NULL ) { *val = dev; + } return err; } -/* - * Initialize the network control interface. Set the number of network devices - * and create them. +/* Get the target interface for a status message. + * Creates the interface when it makes sense. + * The returned interface may be null when there is no error. + * + * @param status status message + * @param np return parameter for interface state + * @return 0 on success, error code otherwise */ +static int target_vif(netif_fe_interface_status_t *status, struct net_private **np) +{ + int err = 0; + struct net_device *dev; -static void netif_driver_status_change( - netif_fe_driver_status_changed_t *status) + DPRINTK("> handle=%d\n", status->handle); + if(status->handle < 0) { + err = -EINVAL; + goto exit; + } + dev = find_dev_by_handle(status->handle); + DPRINTK("> dev=%p\n", dev); + if(dev) goto exit; + // No good - give up. + if(status->status == NETIF_INTERFACE_STATUS_CLOSED) goto exit; + if(status->status == NETIF_INTERFACE_STATUS_CHANGED) goto exit; + // It's a new interface in a good state - create it. + DPRINTK("> create device...\n"); + err = create_netdev(status->handle, &dev); + if(err) goto exit; + netctrl.interface_n++; + exit: + if(np){ + *np = ((dev && !err) ? dev->priv : NULL); + } + DPRINTK("< err=%d\n", err); + return err; +} + +/* Warn about an unexpected status. */ +static void unexpected(struct net_private *np, + netif_fe_interface_status_t *status) +{ + WPRINTK(" Unexpected netif status %s in state %s\n", + status_name[status->status], + be_state_name[np->backend_state]); +} + +/* Handle an interface status message. */ +static void netif_interface_status(netif_fe_interface_status_t *status) { int err = 0; - int i; + struct net_private *np = NULL; + + DPRINTK(">\n"); + DPRINTK("> status=%s handle=%d\n", status_name[status->status], status->handle); - DPRINTK("> max_handle=%d\n", status->max_handle); + err = target_vif(status, &np); + if(err){ + WPRINTK(" Invalid netif: handle=%u\n", status->handle); + return; + } + if(np == NULL){ + DPRINTK("> no vif\n"); + return; + } - /* XXX FIXME: Abuse of 'max_handle' as interface count. */ - netctrl.interface_n = status->max_handle; - netctrl.connected_n = 0; + DPRINTK(">\n"); vif_show(np); - for ( i = 0; i < netctrl.interface_n; i++ ) - { - if ( (err = create_netdev(i, NULL)) != 0 ) - { - netctrl_err(err); + switch (status->status) { + + case NETIF_INTERFACE_STATUS_CLOSED: + switch(np->backend_state){ + + case BEST_CLOSED: + case BEST_DISCONNECTED: + case BEST_CONNECTED: + vif_close(np); + break; + } + break; + + case NETIF_INTERFACE_STATUS_DISCONNECTED: + switch(np->backend_state){ + + case BEST_CLOSED: + vif_disconnect(np); + break; + + case BEST_DISCONNECTED: + case BEST_CONNECTED: + vif_reset(np); + break; + } + break; + + case NETIF_INTERFACE_STATUS_CONNECTED: + switch(np->backend_state){ + + case BEST_CLOSED: + unexpected(np, status); + vif_disconnect(np); + vif_connect(np, status); + break; + + case BEST_DISCONNECTED: + vif_connect(np, status); + break; + + case BEST_CONNECTED: + //todo Do what? + unexpected(np, status); break; } + break; + + case NETIF_INTERFACE_STATUS_CHANGED: + /* The domain controller is notifying us that a device has been + * added or removed. + */ + break; + + default: + WPRINTK(" Invalid netif status code %d\n", status->status); + break; } + vif_show(np); + DPRINTK("<\n"); } +/* + * Initialize the network control interface. + */ +static void netif_driver_status(netif_fe_driver_status_t *status) +{ + DPRINTK("> status=%d\n", status->status); + netctrl.up = status->status; + //netctrl.interface_n = status->max_handle; + //netctrl.connected_n = 0; + netctrl_connected_count(); +} + +/* Receive handler for control messages. */ static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) { - int respond = 1; switch ( msg->subtype ) { - case CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED: - if ( msg->length != sizeof(netif_fe_interface_status_changed_t) ) + case CMSG_NETIF_FE_INTERFACE_STATUS: + if ( msg->length != sizeof(netif_fe_interface_status_t) ) goto error; - netif_status_change((netif_fe_interface_status_changed_t *) - &msg->msg[0]); + netif_interface_status((netif_fe_interface_status_t *) + &msg->msg[0]); break; - case CMSG_NETIF_FE_DRIVER_STATUS_CHANGED: - if ( msg->length != sizeof(netif_fe_driver_status_changed_t) ) + case CMSG_NETIF_FE_DRIVER_STATUS: + if ( msg->length != sizeof(netif_fe_driver_status_t) ) goto error; - netif_driver_status_change((netif_fe_driver_status_changed_t *) - &msg->msg[0]); + netif_driver_status((netif_fe_driver_status_t *) + &msg->msg[0]); break; error: @@ -900,156 +1082,170 @@ static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) break; } - if ( respond ) - ctrl_if_send_response(msg); + ctrl_if_send_response(msg); } -/* Wait for all interfaces to be connected. */ -static int wait_for_interfaces(void) +#if 1 +/* Wait for all interfaces to be connected. + * + * This works OK, but we'd like to use the probing mode (see below). + */ +static int probe_interfaces(void) { int err = 0, conn = 0; int wait_i, wait_n = 100; DPRINTK(">\n"); - for ( wait_i = 0; wait_i < wait_n; wait_i++) - { + for ( wait_i = 0; wait_i < wait_n; wait_i++) { DPRINTK("> wait_i=%d\n", wait_i); conn = netctrl_connected(); if(conn) break; + DPRINTK("> schedule_timeout...\n"); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(10); } - if ( conn <= 0 ) - { + DPRINTK("> wait finished...\n"); + if ( conn <= 0 ) { err = netctrl_err(-ENETDOWN); - printk(KERN_WARNING "[XEN] Failed to connect all virtual interfaces: " - "err=%d\n", err); + WPRINTK(" Failed to connect all virtual interfaces: err=%d\n", err); } DPRINTK("< err=%d\n", err); return err; } +#else +/* Probe for interfaces until no more are found. + * + * This is the mode we'd like to use, but at the moment it panics the kernel. +*/ +static int probe_interfaces(void) +{ + int err = 0; + int wait_i, wait_n = 100; + ctrl_msg_t cmsg = { + .type = CMSG_NETIF_FE, + .subtype = CMSG_NETIF_FE_INTERFACE_STATUS, + .length = sizeof(netif_fe_interface_status_t), + }; + netif_fe_interface_status_t msg = {}; + ctrl_msg_t rmsg = {}; + netif_fe_interface_status_t *reply = (void*)rmsg.msg; + int state = TASK_UNINTERRUPTIBLE; + u32 query = -1; + + DPRINTK(">\n"); + + netctrl.interface_n = 0; + for (wait_i = 0; wait_i < wait_n; wait_i++) { + DPRINTK("> wait_i=%d query=%d\n", wait_i, query); + msg.handle = query; + memcpy(cmsg.msg, &msg, sizeof(msg)); + DPRINTK("> set_current_state...\n"); + set_current_state(state); + DPRINTK("> rmsg=%p msg=%p, reply=%p\n", &rmsg, rmsg.msg, reply); + DPRINTK("> sending...\n"); + err = ctrl_if_send_message_and_get_response(&cmsg, &rmsg, state); + DPRINTK("> err=%d\n", err); + if(err) goto exit; + DPRINTK("> rmsg=%p msg=%p, reply=%p\n", &rmsg, rmsg.msg, reply); + if((int)reply->handle < 0){ + // No more interfaces. + break; + } + query = -reply->handle - 2; + DPRINTK(">netif_interface_status ...\n"); + netif_interface_status(reply); + } + + exit: + if (err) { + err = netctrl_err(-ENETDOWN); + WPRINTK(" Connecting virtual network interfaces failed: err=%d\n", err); + } + + DPRINTK("< err=%d\n", err); + return err; +} + +#endif static int __init netif_init(void) { - ctrl_msg_t cmsg; - netif_fe_driver_status_changed_t st; int err = 0; if ( (start_info.flags & SIF_INITDOMAIN) || (start_info.flags & SIF_NET_BE_DOMAIN) ) return 0; - printk(KERN_INFO "Initialising Xen virtual ethernet frontend driver.\n"); - + IPRINTK(" Initialising virtual ethernet driver.\n"); INIT_LIST_HEAD(&dev_list); - netctrl_init(); - (void)ctrl_if_register_receiver(CMSG_NETIF_FE, netif_ctrlif_rx, CALLBACK_IN_BLOCKING_CONTEXT); - - /* Send a driver-UP notification to the domain controller. */ - cmsg.type = CMSG_NETIF_FE; - cmsg.subtype = CMSG_NETIF_FE_DRIVER_STATUS_CHANGED; - cmsg.length = sizeof(netif_fe_driver_status_changed_t); - st.status = NETIF_DRIVER_STATUS_UP; - st.max_handle = 0; - memcpy(cmsg.msg, &st, sizeof(st)); - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); - - err = wait_for_interfaces(); + send_driver_status(1); + err = probe_interfaces(); if ( err ) ctrl_if_unregister_receiver(CMSG_NETIF_FE, netif_ctrlif_rx); + DPRINTK("< err=%d\n", err); return err; } -void netif_suspend(void) +static void vif_suspend(struct net_private *np) { -#if 1 /* XXX THIS IS TEMPORARY */ - struct net_device *dev = NULL; - struct net_private *np = NULL; - int i; - -/* avoid having tx/rx stuff happen until we're ready */ - - for(i=0;i\n"); + free_irq(np->irq, np->dev); + unbind_evtchn_from_irq(np->evtchn); + DPRINTK("<\n"); +} - sprintf(name,"eth%d",i); - dev = __dev_get_by_name(name); +static void vif_resume(struct net_private *np) +{ + // Connect regardless of whether IFF_UP flag set. + // Stop bad things from happening until we're back up. + DPRINTK(">\n"); + np->backend_state = BEST_DISCONNECTED; + memset(np->tx, 0, PAGE_SIZE); + memset(np->rx, 0, PAGE_SIZE); + + send_interface_connect(np); + DPRINTK("<\n"); +} - if ( dev ) - { - np = dev->priv; - free_irq(np->irq, dev); - unbind_evtchn_from_irq(np->evtchn); - } +void netif_suspend(void) +{ +#if 1 /* XXX THIS IS TEMPORARY */ + struct list_head *ent; + struct net_private *np; + + DPRINTK(">\n"); + list_for_each(ent, &dev_list){ + np = list_entry(ent, struct net_private, list); + vif_suspend(np); } + DPRINTK("<\n"); #endif } void netif_resume(void) { - ctrl_msg_t cmsg; - netif_fe_interface_connect_t up; - struct net_device *dev = NULL; - struct net_private *np = NULL; - int i; - #if 1 /* XXX THIS IS TEMPORARY */ + struct list_head *ent; + struct net_private *np; - for(i=0;ipriv; - - // stop bad things from happening until we're back up - np->backend_state = BEST_DISCONNECTED; - - memset(np->tx,0,PAGE_SIZE); - memset(np->rx,0,PAGE_SIZE); - - cmsg.type = CMSG_NETIF_FE; - cmsg.subtype = CMSG_NETIF_FE_INTERFACE_CONNECT; - cmsg.length = sizeof(netif_fe_interface_connect_t); - up.handle = np->handle; - up.tx_shmem_frame = virt_to_machine(np->tx) >> PAGE_SHIFT; - up.rx_shmem_frame = virt_to_machine(np->rx) >> PAGE_SHIFT; - memcpy(cmsg.msg, &up, sizeof(up)); - - /* Tell the controller to bring up the interface. */ - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); - } + DPRINTK(">\n"); + list_for_each(ent, &dev_list){ + np = list_entry(ent, struct net_private, list); + vif_resume(np); } + DPRINTK("<\n"); #endif - - -#if 0 - /* Send a driver-UP notification to the domain controller. */ - cmsg.type = CMSG_NETIF_FE; - cmsg.subtype = CMSG_NETIF_FE_DRIVER_STATUS_CHANGED; - cmsg.length = sizeof(netif_fe_driver_status_changed_t); - st.status = NETIF_DRIVER_STATUS_UP; - st.max_handle = 0; - memcpy(cmsg.msg, &st, sizeof(st)); - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); -#endif - - } diff --git a/tools/python/xen/lowlevel/xu/xu.c b/tools/python/xen/lowlevel/xu/xu.c index 7bf82e483a..813f357464 100644 --- a/tools/python/xen/lowlevel/xu/xu.c +++ b/tools/python/xen/lowlevel/xu/xu.c @@ -324,11 +324,11 @@ static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args) switch ( TYPE(xum->msg.type, xum->msg.subtype) ) { - case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED): - P2C(blkif_fe_driver_status_changed_t, max_handle, u32); + case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS): + P2C(blkif_fe_driver_status_t, max_handle, u32); break; - case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED): - P2C(netif_fe_driver_status_changed_t, max_handle, u32); + case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS): + P2C(netif_fe_driver_status_t, max_handle, u32); break; } @@ -352,13 +352,13 @@ static PyObject *xu_message_get_payload(PyObject *self, PyObject *args) switch ( TYPE(xum->msg.type, xum->msg.subtype) ) { - case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED): - C2P(blkif_fe_interface_status_changed_t, handle, Int, Long); - C2P(blkif_fe_interface_status_changed_t, status, Int, Long); - C2P(blkif_fe_interface_status_changed_t, evtchn, Int, Long); + case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS): + C2P(blkif_fe_interface_status_t, handle, Int, Long); + C2P(blkif_fe_interface_status_t, status, Int, Long); + C2P(blkif_fe_interface_status_t, evtchn, Int, Long); return dict; - case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED): - C2P(blkif_fe_driver_status_changed_t, status, Int, Long); + case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS): + C2P(blkif_fe_driver_status_t, status, Int, Long); return dict; case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT): C2P(blkif_fe_interface_connect_t, handle, Int, Long); @@ -419,23 +419,23 @@ static PyObject *xu_message_get_payload(PyObject *self, PyObject *args) C2P(blkif_be_vbd_shrink_t, vdevice, Int, Long); C2P(blkif_be_vbd_shrink_t, status, Int, Long); return dict; - case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED): - C2P(blkif_be_driver_status_changed_t, status, Int, Long); + case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS): + C2P(blkif_be_driver_status_t, status, Int, Long); return dict; - case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED): - C2P(netif_fe_interface_status_changed_t, handle, Int, Long); - C2P(netif_fe_interface_status_changed_t, status, Int, Long); - C2P(netif_fe_interface_status_changed_t, evtchn, Int, Long); - C2P(netif_fe_interface_status_changed_t, mac[0], Int, Long); - C2P(netif_fe_interface_status_changed_t, mac[1], Int, Long); - C2P(netif_fe_interface_status_changed_t, mac[2], Int, Long); - C2P(netif_fe_interface_status_changed_t, mac[3], Int, Long); - C2P(netif_fe_interface_status_changed_t, mac[4], Int, Long); - C2P(netif_fe_interface_status_changed_t, mac[5], Int, Long); + case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS): + C2P(netif_fe_interface_status_t, handle, Int, Long); + C2P(netif_fe_interface_status_t, status, Int, Long); + C2P(netif_fe_interface_status_t, evtchn, Int, Long); + C2P(netif_fe_interface_status_t, mac[0], Int, Long); + C2P(netif_fe_interface_status_t, mac[1], Int, Long); + C2P(netif_fe_interface_status_t, mac[2], Int, Long); + C2P(netif_fe_interface_status_t, mac[3], Int, Long); + C2P(netif_fe_interface_status_t, mac[4], Int, Long); + C2P(netif_fe_interface_status_t, mac[5], Int, Long); return dict; - case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED): - C2P(netif_fe_driver_status_changed_t, status, Int, Long); - C2P(netif_fe_driver_status_changed_t, max_handle, Int, Long); + case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS): + C2P(netif_fe_driver_status_t, status, Int, Long); + C2P(netif_fe_driver_status_t, max_handle, Int, Long); return dict; case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT): C2P(netif_fe_interface_connect_t, handle, Int, Long); @@ -468,8 +468,8 @@ static PyObject *xu_message_get_payload(PyObject *self, PyObject *args) C2P(netif_be_disconnect_t, netif_handle, Int, Long); C2P(netif_be_disconnect_t, status, Int, Long); return dict; - case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED): - C2P(netif_be_driver_status_changed_t, status, Int, Long); + case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS): + C2P(netif_be_driver_status_t, status, Int, Long); return dict; } @@ -543,11 +543,11 @@ static PyObject *xu_message_new(PyObject *self, PyObject *args) switch ( TYPE(type, subtype) ) { - case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED): - P2C(blkif_fe_interface_status_changed_t, handle, u32); - P2C(blkif_fe_interface_status_changed_t, status, u32); - P2C(blkif_fe_interface_status_changed_t, evtchn, u16); - P2C(blkif_fe_interface_status_changed_t, domid, u16); + case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS): + P2C(blkif_fe_interface_status_t, handle, u32); + P2C(blkif_fe_interface_status_t, status, u32); + P2C(blkif_fe_interface_status_t, evtchn, u16); + P2C(blkif_fe_interface_status_t, domid, u16); break; case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE): P2C(blkif_be_create_t, domid, u32); @@ -591,17 +591,17 @@ static PyObject *xu_message_new(PyObject *self, PyObject *args) P2C(blkif_be_vbd_shrink_t, blkif_handle, u32); P2C(blkif_be_vbd_shrink_t, vdevice, blkif_vdev_t); break; - case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED): - P2C(netif_fe_interface_status_changed_t, handle, u32); - P2C(netif_fe_interface_status_changed_t, status, u32); - P2C(netif_fe_interface_status_changed_t, evtchn, u16); - P2C(netif_fe_interface_status_changed_t, domid, u16); - P2C(netif_fe_interface_status_changed_t, mac[0], u8); - P2C(netif_fe_interface_status_changed_t, mac[1], u8); - P2C(netif_fe_interface_status_changed_t, mac[2], u8); - P2C(netif_fe_interface_status_changed_t, mac[3], u8); - P2C(netif_fe_interface_status_changed_t, mac[4], u8); - P2C(netif_fe_interface_status_changed_t, mac[5], u8); + case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS): + P2C(netif_fe_interface_status_t, handle, u32); + P2C(netif_fe_interface_status_t, status, u32); + P2C(netif_fe_interface_status_t, evtchn, u16); + P2C(netif_fe_interface_status_t, domid, u16); + P2C(netif_fe_interface_status_t, mac[0], u8); + P2C(netif_fe_interface_status_t, mac[1], u8); + P2C(netif_fe_interface_status_t, mac[2], u8); + P2C(netif_fe_interface_status_t, mac[3], u8); + P2C(netif_fe_interface_status_t, mac[4], u8); + P2C(netif_fe_interface_status_t, mac[5], u8); break; case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE): P2C(netif_be_create_t, domid, u32); @@ -628,9 +628,9 @@ static PyObject *xu_message_new(PyObject *self, PyObject *args) P2C(netif_be_disconnect_t, domid, u32); P2C(netif_be_disconnect_t, netif_handle, u32); break; - case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED): - P2C(netif_fe_driver_status_changed_t, status, u32); - P2C(netif_fe_driver_status_changed_t, max_handle, u32); + case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS): + P2C(netif_fe_driver_status_t, status, u32); + P2C(netif_fe_driver_status_t, max_handle, u32); break; } diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 58b17d2933..ef1a3c2135 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -239,14 +239,14 @@ class XendDomain: destroyed = 0 for d in casualties: id = str(d['dom']) - log.debug('XendDomain>reap> domain died id=%s', id) + dominfo = self.domain_by_id.get(id) + name = (dominfo and dominfo.name) or '??' + log.debug('XendDomain>reap> domain died name=%s id=%s', name, id) if d['shutdown']: reason = XendDomainInfo.shutdown_reason(d['shutdown_reason']) log.debug('XendDomain>reap> shutdown id=%s reason=%s', id, reason) - dominfo = self.domain_by_id.get(id) - name = (dominfo and dominfo.name) or '??' if reason in ['suspend']: - if dominfo.is_terminated(): + if dominfo and dominfo.is_terminated(): log.debug('XendDomain>reap> Suspended domain died id=%s', id) else: eserver.inject('xend.domain.suspended', [name, id]) diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 17a002c665..b24bf186ab 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -155,6 +155,7 @@ def make_disk(vm, config, uname, dev, mode, recreate=0): @param recreate: recreate flag (after xend restart) @return: deferred """ + idx = vm.next_device_index('vbd') segments = lookup_disk_uname(uname) if not segments: raise VmError("vbd: Segments not found: uname=%s" % uname) @@ -166,7 +167,7 @@ def make_disk(vm, config, uname, dev, mode, recreate=0): if not vdev: raise VmError("vbd: Device not found: uname=%s dev=%s" % (uname, dev)) ctrl = xend.blkif_create(vm.dom, recreate=recreate) - return ctrl.attachDevice(config, vdev, mode, segment, recreate=recreate) + return ctrl.attachDevice(idx, config, vdev, mode, segment, recreate=recreate) def vif_up(iplist): """send an unsolicited ARP reply for all non link-local IP addresses. diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py index 60708e24a9..339b99ee12 100755 --- a/tools/python/xen/xend/server/blkif.py +++ b/tools/python/xen/xend/server/blkif.py @@ -19,19 +19,19 @@ class BlkifBackendController(controller.BackendController): def __init__(self, factory, dom): controller.BackendController.__init__(self, factory, dom) self.addMethod(CMSG_BLKIF_BE, - CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED, - self.recv_be_driver_status_changed) + CMSG_BLKIF_BE_DRIVER_STATUS, + self.recv_be_driver_status) self.registerChannel() - def recv_be_driver_status_changed(self, msg, req): - """Request handler for be_driver_status_changed messages. + def recv_be_driver_status(self, msg, req): + """Request handler for be_driver_status messages. @param msg: message @type msg: xu message @param req: request flag (true if the msg is a request) @type req: bool """ - val = unpackMsg('blkif_be_driver_status_changed_t', msg) + val = unpackMsg('blkif_be_driver_status_t', msg) status = val['status'] class BlkifBackendInterface(controller.BackendInterface): @@ -45,10 +45,23 @@ class BlkifBackendInterface(controller.BackendInterface): controller.BackendInterface.__init__(self, ctrl, dom, handle) self.connected = 0 self.evtchn = None + self.status = BLKIF_INTERFACE_STATUS_DISCONNECTED def __str__(self): return '' % (self.controller.dom, self.dom) + def getEventChannelBackend(self): + val = 0 + if self.evtchn: + val = self.evtchn['port1'] + return val + + def getEventChannelFrontend(self): + val = 0 + if self.evtchn: + val = self.evtchn['port2'] + return val + def connect(self, recreate=0): """Connect to the blkif control interface. @@ -105,7 +118,7 @@ class BlkifBackendInterface(controller.BackendInterface): msg = packMsg('blkif_be_connect_t', { 'domid' : self.controller.dom, 'blkif_handle' : self.handle, - 'evtchn' : self.evtchn['port1'], + 'evtchn' : self.getEventChannelBackend(), 'shmem_frame' : val['shmem_frame'] }) d = defer.Deferred() d.addCallback(self.respond_be_connect) @@ -118,31 +131,29 @@ class BlkifBackendInterface(controller.BackendInterface): @type msg: xu message """ val = unpackMsg('blkif_be_connect_t', msg) - self.send_fe_interface_status_changed() + self.status = BLKIF_INTERFACE_STATUS_CONNECTED + self.send_fe_interface_status() - def send_fe_interface_status_changed(self, response=None): - msg = packMsg('blkif_fe_interface_status_changed_t', + def send_fe_interface_status(self, response=None): + msg = packMsg('blkif_fe_interface_status_t', { 'handle' : self.handle, - 'status' : BLKIF_INTERFACE_STATUS_CONNECTED, + 'status' : self.status, 'domid' : self.dom, - 'evtchn' : self.evtchn['port2'] }) + 'evtchn' : self.getEventChannelFrontend() }) self.controller.writeRequest(msg, response=response) def interfaceDisconnected(self): - msg = packMsg('blkif_fe_interface_status_changed_t', - { 'handle' : self.handle, - 'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED, - 'domid' : self.dom, - 'evtchn' : 0 }) - self.controller.writeRequest(msg) + self.status = BLKIF_INTERFACE_STATUS_DISCONNECTED + #todo?: Do this: self.evtchn = None + self.send_fe_interface_status() def interfaceChanged(self): """Notify the front-end that devices have been added or removed. The front-end should then probe for devices. """ - msg = packMsg('blkif_fe_interface_status_changed_t', + msg = packMsg('blkif_fe_interface_status_t', { 'handle' : self.handle, - 'status' : BLKIF_INTERFACE_STATUS_CHANGED, + 'status' : BLKIF_INTERFACE_STATUS, 'domid' : self.dom, 'evtchn' : 0 }) self.controller.writeRequest(msg) @@ -199,25 +210,25 @@ class BlkifControllerFactory(controller.SplitControllerFactory): blkif = self.getControllerByDom(dom) return (blkif and blkif.getDevices()) or [] - def getDomainDevice(self, dom, vdev): + def getDomainDevice(self, dom, idx): """Get a block device from a domain. @param dom: domain @type dom: int - @param vdev: device index - @type vdev: int + @param idx: device index + @type idx: int @return: device @rtype: device """ blkif = self.getControllerByDom(dom) - return (blkif and blkif.getDevice(vdev)) or None + return (blkif and blkif.getDevice(idx)) or None class BlkDev(controller.SplitDev): """Info record for a block device. """ - def __init__(self, ctrl, config, vdev, mode, segment): - controller.SplitDev.__init__(self, segment['device'], ctrl) + def __init__(self, idx, ctrl, config, vdev, mode, segment): + controller.SplitDev.__init__(self, idx, ctrl) self.config = config self.dev = None self.uname = None @@ -251,7 +262,7 @@ class BlkDev(controller.SplitDev): @param change: change flag """ - log.debug("Destroying vbd domain=%d vdev=%d", self.controller.dom, self.vdev) + log.debug("Destroying vbd domain=%d idx=%s", self.controller.dom, self.idx) d = self.send_be_vbd_destroy() if change: d.addCallback(lambda val: self.interfaceChanged()) @@ -345,10 +356,9 @@ class BlkifController(controller.SplitController): Do not call directly - use createController() on the factory instead. """ controller.SplitController.__init__(self, factory, dom) - self.devices = {} self.addMethod(CMSG_BLKIF_FE, - CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED, - self.recv_fe_driver_status_changed) + CMSG_BLKIF_FE_DRIVER_STATUS, + self.recv_fe_driver_status) self.addMethod(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT, self.recv_fe_interface_connect) @@ -358,13 +368,7 @@ class BlkifController(controller.SplitController): val = ['blkif', ['dom', self.dom]] return val - def getDevices(self): - return self.devices.values() - - def getDevice(self, vdev): - return self.devices.get(vdev) - - def addDevice(self, config, vdev, mode, segment): + def addDevice(self, idx, config, vdev, mode, segment): """Add a device to the device table. @param vdev: device index @@ -376,20 +380,18 @@ class BlkifController(controller.SplitController): @return: device @rtype: BlkDev """ - if vdev in self.devices: - raise XendError('device exists: ' + str(vdev)) - dev = BlkDev(self, config, vdev, mode, segment) - self.devices[vdev] = dev + if idx in self.devices: + raise XendError('device exists: ' + str(idx)) + dev = BlkDev(idx, self, config, vdev, mode, segment) + self.devices[idx] = dev return dev - def delDevice(self, vdev): - if vdev in self.devices: - del self.devices[vdev] - - def attachDevice(self, config, vdev, mode, segment, recreate=0): + def attachDevice(self, idx, config, vdev, mode, segment, recreate=0): """Attach a device to the specified interface. On success the returned deferred will be called with the device. + @param idx: device id + @param config: device configuration @param vdev: device index @type vdev: int @param mode: read/write mode @@ -401,7 +403,7 @@ class BlkifController(controller.SplitController): @return: deferred @rtype: Deferred """ - dev = self.addDevice(config, vdev, mode, segment) + dev = self.addDevice(idx, config, vdev, mode, segment) if recreate: d = defer.succeed(dev) else: @@ -425,8 +427,9 @@ class BlkifController(controller.SplitController): for backend in self.getBackendInterfaces(): backend.destroy() - def recv_fe_driver_status_changed(self, msg, req): - val = unpackMsg('blkif_fe_driver_status_changed_t', msg) + def recv_fe_driver_status(self, msg, req): + val = unpackMsg('blkif_fe_driver_status_t', msg) + print 'recv_fe_driver_status>', val for backend in self.getBackendInterfaces(): backend.interfaceDisconnected() @@ -439,5 +442,6 @@ class BlkifController(controller.SplitController): else: log.error('interface connect on unknown interface: handle=%d', handle) + diff --git a/tools/python/xen/xend/server/controller.py b/tools/python/xen/xend/server/controller.py index 71855d8755..3721b9b3b3 100755 --- a/tools/python/xen/xend/server/controller.py +++ b/tools/python/xen/xend/server/controller.py @@ -522,6 +522,9 @@ class BackendInterface: def writeRequest(self, msg, response=None): return self.backend.writeRequest(msg, response=response) + def writeResponse(self, msg): + return self.backend.writeResponse(msg) + def close(self): self.backend.deregisterInterface(self) self.controller.backendInterfaceClosed(self) @@ -536,6 +539,60 @@ class SplitController(Controller): Controller.__init__(self, factory, dom) self.backendInterfaces = {} self.backendHandle = 0 + self.devices = {} + + def getDevices(self): + """Get a list of the devices.. + """ + return self.devices.values() + + def delDevice(self, idx): + """Remove the device with the given index from the device table. + + @param idx device index + """ + if idx in self.devices: + del self.devices[idx] + + def getDevice(self, idx): + """Get the device with a given index. + + @param idx device index + @return device (or None) + """ + return self.devices.get(idx) + + def findDevice(self, idx): + """Find a device. If idx is non-negative, + get the device with the given index. If idx is negative, + look for the device with least index greater than -idx - 2. + For example, if idx is -2, look for devices with index + greater than 0, i.e. 1 or above. + + @param idx device index + @return device (or None) + """ + if idx < 0: + idx = -idx - 2 + val = None + for dev in self.devices.values(): + if dev.idx <= idx: continue + if (val is None) or (dev.idx < val.idx): + val = dev + else: + val = getDevice(idx) + return val + + def getMaxDeviceIdx(self): + """Get the maximum id used by devices. + + @return maximum idx + """ + maxIdx = 0 + for dev in self.devices: + if dev.idx > maxIdx: + maxIdx = dev.idx + return maxIdx def getBackendInterfaces(self): return self.backendInterfaces.values() diff --git a/tools/python/xen/xend/server/messages.py b/tools/python/xen/xend/server/messages.py index fb94214a64..da4980fc96 100644 --- a/tools/python/xen/xend/server/messages.py +++ b/tools/python/xen/xend/server/messages.py @@ -29,70 +29,106 @@ msg_formats.update(console_formats) CMSG_BLKIF_BE = 1 CMSG_BLKIF_FE = 2 -CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED = 0 -CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED = 32 -CMSG_BLKIF_FE_INTERFACE_CONNECT = 33 -CMSG_BLKIF_FE_INTERFACE_DISCONNECT = 34 - -CMSG_BLKIF_BE_CREATE = 0 -CMSG_BLKIF_BE_DESTROY = 1 -CMSG_BLKIF_BE_CONNECT = 2 -CMSG_BLKIF_BE_DISCONNECT = 3 -CMSG_BLKIF_BE_VBD_CREATE = 4 -CMSG_BLKIF_BE_VBD_DESTROY = 5 -CMSG_BLKIF_BE_VBD_GROW = 6 -CMSG_BLKIF_BE_VBD_SHRINK = 7 -CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED = 32 - -BLKIF_DRIVER_STATUS_DOWN = 0 -BLKIF_DRIVER_STATUS_UP = 1 - -BLKIF_INTERFACE_STATUS_DESTROYED = 0 #/* Interface doesn't exist. */ -BLKIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */ -BLKIF_INTERFACE_STATUS_CONNECTED = 2 #/* Exists and is connected. */ -BLKIF_INTERFACE_STATUS_CHANGED = 3 #/* A device has been added or removed. */ - -BLKIF_BE_STATUS_OKAY = 0 -BLKIF_BE_STATUS_ERROR = 1 -BLKIF_BE_STATUS_INTERFACE_EXISTS = 2 -BLKIF_BE_STATUS_INTERFACE_NOT_FOUND = 3 -BLKIF_BE_STATUS_INTERFACE_CONNECTED = 4 -BLKIF_BE_STATUS_VBD_EXISTS = 5 -BLKIF_BE_STATUS_VBD_NOT_FOUND = 6 -BLKIF_BE_STATUS_OUT_OF_MEMORY = 7 -BLKIF_BE_STATUS_EXTENT_NOT_FOUND = 8 -BLKIF_BE_STATUS_MAPPING_ERROR = 9 +CMSG_BLKIF_FE_INTERFACE_STATUS = 0 +CMSG_BLKIF_FE_DRIVER_STATUS = 32 +CMSG_BLKIF_FE_INTERFACE_CONNECT = 33 +CMSG_BLKIF_FE_INTERFACE_DISCONNECT = 34 +CMSG_BLKIF_FE_INTERFACE_QUERY = 35 + +CMSG_BLKIF_BE_CREATE = 0 +CMSG_BLKIF_BE_DESTROY = 1 +CMSG_BLKIF_BE_CONNECT = 2 +CMSG_BLKIF_BE_DISCONNECT = 3 +CMSG_BLKIF_BE_VBD_CREATE = 4 +CMSG_BLKIF_BE_VBD_DESTROY = 5 +CMSG_BLKIF_BE_VBD_GROW = 6 +CMSG_BLKIF_BE_VBD_SHRINK = 7 +CMSG_BLKIF_BE_DRIVER_STATUS = 32 + +BLKIF_DRIVER_STATUS_DOWN = 0 +BLKIF_DRIVER_STATUS_UP = 1 + +BLKIF_INTERFACE_STATUS_CLOSED = 0 #/* Interface doesn't exist. */ +BLKIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */ +BLKIF_INTERFACE_STATUS_CONNECTED = 2 #/* Exists and is connected. */ +BLKIF_INTERFACE_STATUS_CHANGED = 3 #/* A device has been added or removed. */ + +BLKIF_BE_STATUS_OKAY = 0 +BLKIF_BE_STATUS_ERROR = 1 +BLKIF_BE_STATUS_INTERFACE_EXISTS = 2 +BLKIF_BE_STATUS_INTERFACE_NOT_FOUND = 3 +BLKIF_BE_STATUS_INTERFACE_CONNECTED = 4 +BLKIF_BE_STATUS_VBD_EXISTS = 5 +BLKIF_BE_STATUS_VBD_NOT_FOUND = 6 +BLKIF_BE_STATUS_OUT_OF_MEMORY = 7 +BLKIF_BE_STATUS_EXTENT_NOT_FOUND = 8 +BLKIF_BE_STATUS_MAPPING_ERROR = 9 blkif_formats = { 'blkif_be_connect_t': (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT), + # Connect be to fe (in response to blkif_fe_interface_connect_t). 'blkif_be_create_t': (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE), + # Create be. 'blkif_be_disconnect_t': (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT), + # Disconnect be from fe. 'blkif_be_destroy_t': (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY), + # Destroy be (after disconnect). + # Make be do this even if no disconnect (and destroy all vbd too). 'blkif_be_vbd_create_t': (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE), + # Create a vbd device. 'blkif_be_vbd_grow_t': (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW), + # Change the size of a vbd device. Remove? + # Do in one go in blkif_be_vbd_create_t. 'blkif_be_vbd_destroy_t': (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY), - - 'blkif_fe_interface_status_changed_t': - (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED), - - 'blkif_fe_driver_status_changed_t': - (CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED), + # Destroy a vbd. + + # Add message to query be for state and vbds. + + 'blkif_fe_interface_status_t': + (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS), + # Notify device status to fe. + # Also used to notify 'any' device change with status BLKIF_INTERFACE_STATUS_CHANGED. + # Rename to blkif_fe_interface_status. + + 'blkif_fe_driver_status_t': + (CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS), + # Comes from fe, treated as notifying that fe has come up/changed. + # Xend sets be(s) to BLKIF_INTERFACE_STATUS_DISCONNECTED, + # sends blkif_fe_interface_status_t to fe (from each be). + # + # Rename to blkif_fe_driver_status. + # Reply with i/f count. + # The i/f sends probes (using -ve trick), we reply with the info. 'blkif_fe_interface_connect_t': (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT), + # Comes from fe, passing shmem frame to use for be. + # fe sends when gets blkif_fe_interface_status_t with state NETIF_INTERFACE_STATUS_DISCONNECTED. + # Xend creates event channel and notifies be. + # Then notifies fe of event channel with blkif_fe_interface_status_t. + + # Add message to kick fe to probe for devices. + # Just report new devices to fe? + + # + # Add message for fe to probe a device. + # And probing with id -1 should return first. + # And probing with id -n should return first device with id > n. + + # Add message to query fe for state and vbds. } msg_formats.update(blkif_formats) @@ -104,24 +140,25 @@ msg_formats.update(blkif_formats) CMSG_NETIF_BE = 3 CMSG_NETIF_FE = 4 -CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED = 0 -CMSG_NETIF_FE_DRIVER_STATUS_CHANGED = 32 -CMSG_NETIF_FE_INTERFACE_CONNECT = 33 -CMSG_NETIF_FE_INTERFACE_DISCONNECT = 34 +CMSG_NETIF_FE_INTERFACE_STATUS = 0 +CMSG_NETIF_FE_DRIVER_STATUS = 32 +CMSG_NETIF_FE_INTERFACE_CONNECT = 33 +CMSG_NETIF_FE_INTERFACE_DISCONNECT = 34 +CMSG_NETIF_FE_INTERFACE_QUERY = 35 -CMSG_NETIF_BE_CREATE = 0 -CMSG_NETIF_BE_DESTROY = 1 -CMSG_NETIF_BE_CONNECT = 2 -CMSG_NETIF_BE_DISCONNECT = 3 -CMSG_NETIF_BE_DRIVER_STATUS_CHANGED = 32 +CMSG_NETIF_BE_CREATE = 0 +CMSG_NETIF_BE_DESTROY = 1 +CMSG_NETIF_BE_CONNECT = 2 +CMSG_NETIF_BE_DISCONNECT = 3 +CMSG_NETIF_BE_DRIVER_STATUS = 32 -NETIF_INTERFACE_STATUS_DESTROYED = 0 #/* Interface doesn't exist. */ -NETIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */ -NETIF_INTERFACE_STATUS_CONNECTED = 2 #/* Exists and is connected. */ -NETIF_INTERFACE_STATUS_CHANGED = 3 #/* A device has been added or removed. */ +NETIF_INTERFACE_STATUS_CLOSED = 0 #/* Interface doesn't exist. */ +NETIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */ +NETIF_INTERFACE_STATUS_CONNECTED = 2 #/* Exists and is connected. */ +NETIF_INTERFACE_STATUS_CHANGED = 3 #/* A device has been added or removed. */ -NETIF_DRIVER_STATUS_DOWN = 0 -NETIF_DRIVER_STATUS_UP = 1 +NETIF_DRIVER_STATUS_DOWN = 0 +NETIF_DRIVER_STATUS_UP = 1 netif_formats = { 'netif_be_connect_t': @@ -136,17 +173,17 @@ netif_formats = { 'netif_be_destroy_t': (CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY), - 'netif_be_driver_status_changed_t': - (CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED), + 'netif_be_driver_status_t': + (CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS), - 'netif_fe_driver_status_changed_t': - (CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED), + 'netif_fe_driver_status_t': + (CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS), 'netif_fe_interface_connect_t': (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT), - 'netif_fe_interface_status_changed_t': - (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED), + 'netif_fe_interface_status_t': + (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS), } msg_formats.update(netif_formats) @@ -241,13 +278,15 @@ def unpackMsg(ty, msg): macs = [] for (k, v) in args.items(): if k.startswith('mac['): - macs += k + macs.append(k) i = int(k[4:5]) mac[i] = v else: pass if macs: args['mac'] = mac + print 'macs=', macs + print 'args=', args for k in macs: del args[k] if DEBUG: diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py index 84f569d830..38e722347a 100755 --- a/tools/python/xen/xend/server/netif.py +++ b/tools/python/xen/xend/server/netif.py @@ -24,12 +24,12 @@ class NetifBackendController(controller.BackendController): def __init__(self, ctrl, dom): controller.BackendController.__init__(self, ctrl, dom) self.addMethod(CMSG_NETIF_BE, - CMSG_NETIF_BE_DRIVER_STATUS_CHANGED, - self.recv_be_driver_status_changed) + CMSG_NETIF_BE_DRIVER_STATUS, + self.recv_be_driver_status) self.registerChannel() - def recv_be_driver_status_changed(self, msg, req): - val = unpackMsg('netif_be_driver_status_changed_t', msg) + def recv_be_driver_status(self, msg, req): + val = unpackMsg('netif_be_driver_status_t', msg) status = val['status'] class NetifBackendInterface(controller.BackendInterface): @@ -98,11 +98,12 @@ class NetDev(controller.SplitDev): """Info record for a network device. """ - def __init__(self, ctrl, vif, config): + def __init__(self, vif, ctrl, config): controller.SplitDev.__init__(self, vif, ctrl) self.vif = vif self.evtchn = None self.configure(config) + self.status = NETIF_INTERFACE_STATUS_DISCONNECTED def _get_config_mac(self, config): vmac = sxp.child_value(config, 'mac') @@ -245,6 +246,18 @@ class NetDev(controller.SplitDev): d.addCallback(self.respond_be_create) return d + def getEventChannelBackend(self): + val = 0 + if self.evtchn: + val = self.evtchn['port1'] + return val + + def getEventChannelFrontend(self): + val = 0 + if self.evtchn: + val = self.evtchn['port2'] + return val + def send_be_create(self): d = defer.Deferred() msg = packMsg('netif_be_create_t', @@ -264,11 +277,12 @@ class NetDev(controller.SplitDev): @param change: change flag """ + self.status = NETIF_INTERFACE_STATUS_CLOSED def cb_destroy(val): self.send_be_destroy() self.getBackendInterface().close() if change: - self.interfaceChanged() + self.reportStatus() log.debug("Destroying vif domain=%d vif=%d", self.controller.dom, self.vif) self.vifctl('down') d = self.send_be_disconnect() @@ -295,7 +309,7 @@ class NetDev(controller.SplitDev): msg = packMsg('netif_be_connect_t', { 'domid' : self.controller.dom, 'netif_handle' : self.vif, - 'evtchn' : self.evtchn['port1'], + 'evtchn' : self.getEventChannelBackend(), 'tx_shmem_frame' : val['tx_shmem_frame'], 'rx_shmem_frame' : val['rx_shmem_frame'] }) d = defer.Deferred() @@ -306,34 +320,25 @@ class NetDev(controller.SplitDev): val = unpackMsg('netif_be_connect_t', msg) dom = val['domid'] vif = val['netif_handle'] - msg = packMsg('netif_fe_interface_status_changed_t', - { 'handle' : self.vif, - 'status' : NETIF_INTERFACE_STATUS_CONNECTED, - 'evtchn' : self.evtchn['port2'], - 'domid' : self.backendDomain, - 'mac' : self.mac }) - self.controller.writeRequest(msg) + self.status = NETIF_INTERFACE_STATUS_CONNECTED + self.reportStatus() - def attach_fe_device(self): - msg = packMsg('netif_fe_interface_status_changed_t', + def reportStatus(self, resp=0): + msg = packMsg('netif_fe_interface_status_t', { 'handle' : self.vif, - 'status' : NETIF_INTERFACE_STATUS_DISCONNECTED, - 'evtchn' : 0, + 'status' : self.status, + 'evtchn' : self.getEventChannelFrontend(), 'domid' : self.backendDomain, 'mac' : self.mac }) - self.controller.writeRequest(msg) + if resp: + self.controller.writeResponse(msg) + else: + self.controller.writeRequest(msg) def interfaceChanged(self): """Notify the font-end that a device has been added or removed. - The front-end should then probe the devices. """ - msg = packMsg('netif_fe_interface_status_changed_t', - { 'handle' : self.vif, - 'status' : NETIF_INTERFACE_STATUS_CHANGED, - 'evtchn' : 0, - 'domid' : self.backendDomain, - 'mac' : self.mac }) - self.controller.writeRequest(msg) + self.reportStatus() class NetifController(controller.SplitController): """Network interface controller. Handles all network devices for a domain. @@ -343,8 +348,11 @@ class NetifController(controller.SplitController): controller.SplitController.__init__(self, factory, dom) self.devices = {} self.addMethod(CMSG_NETIF_FE, - CMSG_NETIF_FE_DRIVER_STATUS_CHANGED, - self.recv_fe_driver_status_changed) + CMSG_NETIF_FE_DRIVER_STATUS, + self.recv_fe_driver_status) + self.addMethod(CMSG_NETIF_FE, + CMSG_NETIF_FE_INTERFACE_STATUS, + self.recv_fe_interface_status) self.addMethod(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT, self.recv_fe_interface_connect) @@ -359,19 +367,6 @@ class NetifController(controller.SplitController): """ controller.Controller.lostChannel(self) - def getDevices(self): - """Get a list of the devices. - """ - return self.devices.values() - - def getDevice(self, vif): - """Get a device. - - @param vif: device index - @return: device (or None) - """ - return self.devices.get(vif) - def addDevice(self, vif, config): """Add a network interface. @@ -381,14 +376,10 @@ class NetifController(controller.SplitController): """ if vif in self.devices: raise XendError('device exists:' + str(vif)) - dev = NetDev(self, vif, config) + dev = NetDev(vif, self, config) self.devices[vif] = dev return dev - def delDevice(self, vif): - if vif in self.devices: - del self.devices[vif] - def destroy(self): """Destroy the controller and all devices. """ @@ -415,23 +406,64 @@ class NetifController(controller.SplitController): d = dev.attach() return d - def recv_fe_driver_status_changed(self, msg, req): + def recv_fe_driver_status(self, msg, req): if not req: return - msg = packMsg('netif_fe_driver_status_changed_t', + print + print 'recv_fe_driver_status>' + msg = packMsg('netif_fe_driver_status_t', { 'status' : NETIF_DRIVER_STATUS_UP, ## FIXME: max_handle should be max active interface id - 'max_handle' : len(self.devices) }) - self.writeRequest(msg) - for dev in self.devices.values(): - dev.attach_fe_device() + 'max_handle' : len(self.devices) + #'max_handle' : self.getMaxDeviceIdx() + }) + # Two ways of doing it: + # 1) front-end requests driver status, we reply with the interface count, + # front-end polls the interfaces, + # front-end checks they are all up + # 2) front-end requests driver status, we reply (with anything), + # we notify the interfaces, + # we notify driver status up with the count + # front-end checks they are all up + # + # We really want to use 1), but at the moment the xenU kernel panics + # in that mode, so we're sticking to 2) for now. + resp = 0 + if resp: + self.writeResponse(msg) + else: + for dev in self.devices.values(): + dev.reportStatus() + self.writeRequest(msg) + return resp + + def recv_fe_interface_status(self, msg, req): + if not req: return + print + val = unpackMsg('netif_fe_interface_status_t', msg) + print "recv_fe_interface_status>", val + vif = val['handle'] + dev = self.findDevice(vif) + if dev: + print 'recv_fe_interface_status>', 'dev=', dev + dev.reportStatus(resp=1) + else: + msg = packMsg('netif_fe_interface_status_t', + { 'handle' : -1, + 'status' : NETIF_INTERFACE_STATUS_CLOSED, + }); + print 'recv_fe_interface_status>', 'no dev, returning -1' + self.writeResponse(msg) + return 1 + def recv_fe_interface_connect(self, msg, req): val = unpackMsg('netif_fe_interface_connect_t', msg) vif = val['handle'] - dev = self.devices.get(vif) + print + print "recv_fe_interface_connect", val + dev = self.getDevice(vif) if dev: dev.recv_fe_interface_connect(val, req) else: log.error('Received netif_fe_interface_connect for unknown vif: dom=%d vif=%d', self.dom, vif) - diff --git a/xen/include/hypervisor-ifs/io/domain_controller.h b/xen/include/hypervisor-ifs/io/domain_controller.h index 5de3c2d673..5f9a20f861 100644 --- a/xen/include/hypervisor-ifs/io/domain_controller.h +++ b/xen/include/hypervisor-ifs/io/domain_controller.h @@ -70,10 +70,10 @@ typedef struct { */ /* Messages from domain controller to guest. */ -#define CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED 0 +#define CMSG_BLKIF_FE_INTERFACE_STATUS 0 /* Messages from guest to domain controller. */ -#define CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED 32 +#define CMSG_BLKIF_FE_DRIVER_STATUS 32 #define CMSG_BLKIF_FE_INTERFACE_CONNECT 33 #define CMSG_BLKIF_FE_INTERFACE_DISCONNECT 34 #define CMSG_BLKIF_FE_INTERFACE_QUERY 35 @@ -84,25 +84,25 @@ typedef struct { #define blkif_sector_t u64 /* - * CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED: + * CMSG_BLKIF_FE_INTERFACE_STATUS: * Notify a guest about a status change on one of its block interfaces. * If the interface is DESTROYED or DOWN then the interface is disconnected: * 1. The shared-memory frame is available for reuse. * 2. Any unacknowledged messages pending on the interface were dropped. */ -#define BLKIF_INTERFACE_STATUS_DESTROYED 0 /* Interface doesn't exist. */ +#define BLKIF_INTERFACE_STATUS_CLOSED 0 /* Interface doesn't exist. */ #define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */ #define BLKIF_INTERFACE_STATUS_CONNECTED 2 /* Exists and is connected. */ -#define BLKIF_INTERFACE_STATUS_CHANGED 3 /* A device has been added or removed. */ +//#define BLKIF_INTERFACE_STATUS_CHANGED 3 /* A device has been added or removed. */ typedef struct { u32 handle; /* 0 */ u32 status; /* 4 */ u16 evtchn; /* 8: (only if status == BLKIF_INTERFACE_STATUS_CONNECTED). */ domid_t domid; /* 10: status != BLKIF_INTERFACE_STATUS_DESTROYED */ -} PACKED blkif_fe_interface_status_changed_t; /* 12 bytes */ +} PACKED blkif_fe_interface_status_t; /* 12 bytes */ /* - * CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED: + * CMSG_BLKIF_FE_DRIVER_STATUS: * Notify the domain controller that the front-end driver is DOWN or UP. * When the driver goes DOWN then the controller will send no more * status-change notifications. @@ -121,7 +121,7 @@ typedef struct { /* OUT */ /* Driver should query interfaces [0..max_handle]. */ u32 max_handle; /* 4 */ -} PACKED blkif_fe_driver_status_changed_t; /* 8 bytes */ +} PACKED blkif_fe_driver_status_t; /* 8 bytes */ /* * CMSG_BLKIF_FE_INTERFACE_CONNECT: @@ -172,7 +172,7 @@ typedef struct { #define CMSG_BLKIF_BE_VBD_SHRINK 7 /* Remove last extent from a given VBD. */ /* Messages to domain controller. */ -#define CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED 32 +#define CMSG_BLKIF_BE_DRIVER_STATUS 32 /* * Message request/response definitions for block-device messages. @@ -325,14 +325,14 @@ typedef struct { } PACKED blkif_be_vbd_shrink_t; /* 16 bytes */ /* - * CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED: + * CMSG_BLKIF_BE_DRIVER_STATUS: * Notify the domain controller that the back-end driver is DOWN or UP. * If the driver goes DOWN while interfaces are still UP, the controller * will automatically send DOWN notifications. */ typedef struct { u32 status; /* 0: BLKIF_DRIVER_STATUS_??? */ -} PACKED blkif_be_driver_status_changed_t; /* 4 bytes */ +} PACKED blkif_be_driver_status_t; /* 4 bytes */ /****************************************************************************** @@ -340,22 +340,22 @@ typedef struct { */ /* Messages from domain controller to guest. */ -#define CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED 0 +#define CMSG_NETIF_FE_INTERFACE_STATUS 0 /* Messages from guest to domain controller. */ -#define CMSG_NETIF_FE_DRIVER_STATUS_CHANGED 32 +#define CMSG_NETIF_FE_DRIVER_STATUS 32 #define CMSG_NETIF_FE_INTERFACE_CONNECT 33 #define CMSG_NETIF_FE_INTERFACE_DISCONNECT 34 #define CMSG_NETIF_FE_INTERFACE_QUERY 35 /* - * CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED: + * CMSG_NETIF_FE_INTERFACE_STATUS: * Notify a guest about a status change on one of its network interfaces. - * If the interface is DESTROYED or DOWN then the interface is disconnected: + * If the interface is CLOSED or DOWN then the interface is disconnected: * 1. The shared-memory frame is available for reuse. * 2. Any unacknowledged messgaes pending on the interface were dropped. */ -#define NETIF_INTERFACE_STATUS_DESTROYED 0 /* Interface doesn't exist. */ +#define NETIF_INTERFACE_STATUS_CLOSED 0 /* Interface doesn't exist. */ #define NETIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */ #define NETIF_INTERFACE_STATUS_CONNECTED 2 /* Exists and is connected. */ #define NETIF_INTERFACE_STATUS_CHANGED 3 /* A device has been added or removed. */ @@ -365,17 +365,17 @@ typedef struct { u16 evtchn; /* 8: status == NETIF_INTERFACE_STATUS_CONNECTED */ u8 mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */ domid_t domid; /* 16: status != NETIF_INTERFACE_STATUS_DESTROYED */ -} PACKED netif_fe_interface_status_changed_t; /* 18 bytes */ +} PACKED netif_fe_interface_status_t; /* 18 bytes */ /* - * CMSG_NETIF_FE_DRIVER_STATUS_CHANGED: + * CMSG_NETIF_FE_DRIVER_STATUS: * Notify the domain controller that the front-end driver is DOWN or UP. * When the driver goes DOWN then the controller will send no more * status-change notifications. * If the driver goes DOWN while interfaces are still UP, the domain * will automatically take the interfaces DOWN. * - * NB. The controller should not send an INTERFACE_STATUS_CHANGED message + * NB. The controller should not send an INTERFACE_STATUS message * for interfaces that are active when it receives an UP notification. We * expect that the frontend driver will query those interfaces itself. */ @@ -387,7 +387,7 @@ typedef struct { /* OUT */ /* Driver should query interfaces [0..max_handle]. */ u32 max_handle; /* 4 */ -} PACKED netif_fe_driver_status_changed_t; /* 8 bytes */ +} PACKED netif_fe_driver_status_t; /* 8 bytes */ /* * CMSG_NETIF_FE_INTERFACE_CONNECT: @@ -437,7 +437,7 @@ typedef struct { #define CMSG_NETIF_BE_DISCONNECT 3 /* Disconnect i/f from remote driver. */ /* Messages to domain controller. */ -#define CMSG_NETIF_BE_DRIVER_STATUS_CHANGED 32 +#define CMSG_NETIF_BE_DRIVER_STATUS 32 /* * Message request/response definitions for net-device messages. @@ -533,14 +533,14 @@ typedef struct { } PACKED netif_be_disconnect_t; /* 12 bytes */ /* - * CMSG_NETIF_BE_DRIVER_STATUS_CHANGED: + * CMSG_NETIF_BE_DRIVER_STATUS: * Notify the domain controller that the back-end driver is DOWN or UP. * If the driver goes DOWN while interfaces are still UP, the domain * will automatically send DOWN notifications. */ typedef struct { u32 status; /* 0: NETIF_DRIVER_STATUS_??? */ -} PACKED netif_be_driver_status_changed_t; /* 4 bytes */ +} PACKED netif_be_driver_status_t; /* 4 bytes */ /******************************************************************************